/******************************************************************************
 Copyright (c) 2021-2025 Qualcomm Technologies International, Ltd.
 All Rights Reserved.
 Qualcomm Technologies International, Ltd. Confidential and Proprietary.

******************************************************************************/

#include "csr_bt_gatt_lib.h"
#include "gatt_battery_server.h"
#include "gatt_battery_server_access.h"
#include "gatt_battery_server_private.h"
#include "gatt_battery_server_db.h"

/****************************************************************************/
bool GattBatteryServerSendLevelNotification(const GBASS *battery_server, uint16 number_cids, const uint32 *cids, uint8 battery_level)
{
    bool result = FALSE;
    uint16 index = 0;
    CSR_UNUSED(battery_server);

    if ((battery_server != NULL) && (battery_level <= 100) && number_cids)
    {
        if (battery_server->notifications_enabled)
        {
            uint16 handle = HANDLE_BATTERY_LEVEL;
#ifndef CSR_BT_GATT_INSTALL_FLAT_DB
            handle += battery_server->start_handle;
#endif
            result = TRUE;

            for (index = 0; index < number_cids; index++)
            {
                if (cids[index] == 0)
                {
                    /* CID must be non-zero */
                    result = FALSE;
                }
                else
                {
                    /* Send notification */
                    uint8 *value = (uint8*) CsrPmemAlloc(GATT_BATTERY_LEVEL_OCTET_SIZE);
                    SynMemCpyS(value, GATT_BATTERY_LEVEL_OCTET_SIZE, &battery_level, GATT_BATTERY_LEVEL_OCTET_SIZE);
                    CsrBtGattNotificationEventReqSend(battery_server->gattId, cids[index], handle, GATT_BATTERY_LEVEL_OCTET_SIZE, value);
                }
            }
            
        }
        else
        {
            result = FALSE;
        }
    }

    return result;
}

#ifndef EXCLUDE_GATT_BATTERY_SERVICE_V1P1

/****************************************************************************/
bool GattBatteryServerSendBatteryLevelStatusNotification(const GBASS* batteryServer, uint16 numberCids, const uint32* cids, GattBatteryLevelStatus batteryLevelStatus)
{
    bool result = FALSE;
    uint16 index = 0;
    CSR_UNUSED(batteryServer);
    if ((batteryServer != NULL) && (batteryLevelStatus.flags < 8) && numberCids)
    {
        if (batteryServer->notifications_enabled)
        {
            result = TRUE;
            for (index = 0; index < numberCids; index++)
            {
                if (cids[index] == 0)
                {
                    /* CID must be non-zero */
                    result = FALSE;
                }
                else
                {
                    uint8* value = (uint8*)CsrPmemAlloc(GATT_BATTERY_LEVEL_STATUS_OCTET_SIZE);
                    uint8* octate = value;
                    uint8 size = 3;
                    SynMemCpyS(octate, GATT_BATTERY_LEVEL_STATUS_OCTET_SIZE, &batteryLevelStatus.flags, GATT_BATTERY_FLAGS_SIZE);
                    octate += GATT_BATTERY_FLAGS_SIZE;
                    SynMemCpyS(octate, GATT_BATTERY_LEVEL_STATUS_OCTET_SIZE, &batteryLevelStatus.powerState, GATT_BATTERY_LEVEL_STATUS_POWER_STATE_SIZE);
                    octate += GATT_BATTERY_LEVEL_STATUS_POWER_STATE_SIZE;
                    if (batteryLevelStatus.flags & IDENTIFIER_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_LEVEL_STATUS_OCTET_SIZE, &batteryLevelStatus.identifier, GATT_BATTERY_LEVEL_STATUS_IDENTIFIER_OCTET_SIZE);
                        octate += GATT_BATTERY_LEVEL_STATUS_IDENTIFIER_OCTET_SIZE;
                        size += GATT_BATTERY_LEVEL_STATUS_IDENTIFIER_OCTET_SIZE;
                    }
                    if (batteryLevelStatus.flags & BATTERY_LEVEL_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_LEVEL_STATUS_OCTET_SIZE, &batteryLevelStatus.batteryLevel, GATT_BATTERY_LEVEL_OCTET_SIZE);
                        octate += GATT_BATTERY_LEVEL_OCTET_SIZE;
                        size += GATT_BATTERY_LEVEL_OCTET_SIZE;
                    }
                    if (batteryLevelStatus.flags & ADDITIONAL_STATUS_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_LEVEL_STATUS_OCTET_SIZE, &batteryLevelStatus.additionalStatus, GATT_BATTERY_LEVEL_STATUS_ADDITIONAL_STATUS_OCTET_SIZE);
                        octate += GATT_BATTERY_LEVEL_STATUS_ADDITIONAL_STATUS_OCTET_SIZE;
                        size += GATT_BATTERY_LEVEL_STATUS_ADDITIONAL_STATUS_OCTET_SIZE;
                    }
                    octate = NULL;
                    CsrBtGattNotificationEventReqSend(batteryServer->gattId, cids[index], HANDLE_BATTERY_LEVEL_STATUS, size, value);
                }
            }
        }
        else
        {
            result = FALSE;
        }
    }
    return result;
}

/****************************************************************************/
bool GattBatteryServerSendEstimatedServiceDateNotification(const GBASS* batteryServer, uint16 numberCids, const uint32* cids, uint32 estimatedServiceDate)
{
    bool result = FALSE;
    uint16 index = 0;
    CSR_UNUSED(batteryServer);
    if ((batteryServer != NULL) && (estimatedServiceDate <= 16777214) && numberCids)
    {
        if (batteryServer->notifications_enabled)
        {
            result = TRUE;
            for (index = 0; index < numberCids; index++)
            {
                if (cids[index] == 0)
                {
                    /* CID must be non-zero */
                    result = FALSE;
                }
                else
                {
                    /* Send notification */
                    uint8* value = (uint8*)CsrPmemAlloc(GATT_ESTIMATED_SERVICE_DATE_OCTET_SIZE);
                    SynMemCpyS(value, GATT_ESTIMATED_SERVICE_DATE_OCTET_SIZE, &estimatedServiceDate, GATT_ESTIMATED_SERVICE_DATE_OCTET_SIZE);
                    CsrBtGattNotificationEventReqSend(batteryServer->gattId, cids[index], HANDLE_ESTIMATED_SERVICE_DATE, GATT_ESTIMATED_SERVICE_DATE_OCTET_SIZE, value);
                }
            }
        }
        else
        {
            result = FALSE;
        }
    }
    return result;
}

/****************************************************************************/
bool GattBatteryServerSendBatteryEnergyStatusNotification(const GBASS* batteryServer, uint16 numberCids, const uint32* cids, GattBatteryEnergyStatus batteryEnergyStatus)
{
    bool result = FALSE;
    uint16 index = 0;
    CSR_UNUSED(batteryServer);
    if ((batteryServer != NULL) && (batteryEnergyStatus.flags < 64) && numberCids)
    {
        if (batteryServer->notifications_enabled)
        {
            result = TRUE;
            for (index = 0; index < numberCids; index++)
            {
                if (cids[index] == 0)
                {
                    /* CID must be non-zero */
                    result = FALSE;
                }
                else
                {
                    /* Send notification */
                    uint8* value = (uint8*)CsrPmemAlloc(GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE);
                    uint8* octate = value;
                    uint16 size = 1;
                    SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus, GATT_BATTERY_FLAGS_SIZE);
                    octate += GATT_BATTERY_FLAGS_SIZE;
                    if (batteryEnergyStatus.flags & EXTERNAL_SOURCE_POWER_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus.externalSourcePower, GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE);
                        octate += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                        size += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                    }
                    if (batteryEnergyStatus.flags & PRESENT_VOLTAGE_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus.presentVoltage, GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE);
                        octate += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                        size += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                    }
                    if (batteryEnergyStatus.flags & AVAILABLE_ENERGY_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus.availableEnergy, GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE);
                        octate += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                        size += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                    }
                    if (batteryEnergyStatus.flags & AVAILABLE_BATTERY_CAPACITY_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus.availableBatteryCapacity, GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE);
                        octate += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                        size += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                    }
                    if (batteryEnergyStatus.flags & CHARGE_RATE_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus.chargeRate, GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE);
                        octate += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                        size += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                    }
                    if (batteryEnergyStatus.flags & AVAILABLE_ENERGY_AT_LAST_CHARGE_PRESENT)
                    {
                        SynMemCpyS(octate, GATT_BATTERY_ENERGY_STATUS_OCTET_SIZE, &batteryEnergyStatus.availableEnergyAtLastCharge, GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE);
                        octate += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                        size += GATT_BATTERY_ENERGY_STATUS_FIELDS_OCTET_SIZE;
                    }
                    octate = NULL;
                    CsrBtGattNotificationEventReqSend(batteryServer->gattId, cids[index], HANDLE_BATTERY_ENERGY_STATUS, size, value);
                }
            }
        }
        else
        {
            result = FALSE;
        }
    }
    return result;
}

/****************************************************************************/
bool GattBatteryServerSendBatteryTimeStatusNotification(const GBASS* batteryServer, uint16 numberCids, const uint32* cids, GattBatteryTimeStatus currentBatteryTimeStatus)
{
    bool result = FALSE;
    uint16 index = 0;
    CSR_UNUSED(currentBatteryTimeStatus);
    if (batteryServer != NULL)
    {
        if (batteryServer->notifications_enabled)
        {
            result = TRUE;
            for (index = 0; index < numberCids; index++)
            {
                if (cids[index] == 0)
                {
                    /* CID must be non-zero */
                    result = FALSE;
                }
                else
                {
                    /* Send notification */
                    /*
                        The battery time status inclued the the bit masking flags(mandatory) - 1 octet,
                        Estimated time in minutes until discharged(mandatory) - 3 octets,
                        Estimated time in minutes until discharged assuming for the remaining time the device is in standby(present if bit 0 of flags is set to 1) - 0 or 3 octets,
                        Estimated time in minutes until recharged(present if bit 1 of flags is set to 1) - 0 or 3 octets.
                    */
                    uint8* value = (uint8*)CsrPmemAlloc(sizeof(GattBatteryTimeStatus));
                    uint8* temp = value, size_value = 4;
                    SynMemCpyS(temp, sizeof(GattBatteryTimeStatus), &currentBatteryTimeStatus.batteryTimeStatusFlags, sizeof(uint8));
                    temp++;
                    SynMemCpyS(temp, sizeof(GattBatteryTimeStatus), &currentBatteryTimeStatus.timeUntilDischarged, 3 * sizeof(uint8));
                    temp += 3;
                    if (currentBatteryTimeStatus.batteryTimeStatusFlags & TIME_UNTIL_DISCHARGED_ON_STANDBY_PRESENT) 
                    {
                        size_value += 3;
                        SynMemCpyS(temp, sizeof(GattBatteryTimeStatus), &currentBatteryTimeStatus.timeUntilDischargedOnStandby, 3 * sizeof(uint8));
                        temp += 3;
                    }
                    if (currentBatteryTimeStatus.batteryTimeStatusFlags & TIME_UNTIL_RECHARGED_PRESENT) 
                    {
                        size_value += 3;
                        SynMemCpyS(temp, sizeof(GattBatteryTimeStatus), &currentBatteryTimeStatus.timeUntilRecharged, 3 * sizeof(uint8));
                        temp += 3;
                    }
                    CsrBtGattNotificationEventReqSend(batteryServer->gattId, cids[index], HANDLE_BATTERY_TIME_STATUS, size_value, value);
                }
            }
        }
        else
        {
            result = FALSE;
        }
    }
    return result;
}

/****************************************************************************/
bool GattBatteryServerSendBatteryHealthStatusNotification(const GBASS* batteryServer, uint16 numberCids, const uint32* cids, GattBatteryHealthStatus batteryHealthStatus)
{
    bool result = FALSE;
    uint16 index = 0;
    CSR_UNUSED(batteryHealthStatus);
    if (batteryServer != NULL)
    {
        if (batteryServer->notifications_enabled)
        {
            result = TRUE;
            for (index = 0; index < numberCids; index++)
            {
                if (cids[index] == 0)
                {
                    /* CID must be non-zero */
                    result = FALSE;
                }
                else
                {
                    /* Send notification */
                    /*
                        The battery health status inclued the the bit masking flags(mandatory) - 1 octet,
                        Battery health summary(present if bit 0 of flags is set to 1) - 0 or 1 octet,
                        Cycle count(present if bit 1 of flags is set to 1) - 0 or 2 octets,
                        Current Temperature(present if bit 2 of flags is set to 1) - 0 or 1 octet,
                        Deep Discharge Count(present if bit 3 of flags is set to 1) - 0 or 2 octets.
                    */
                    GattBatteryHealthStatus* value = (GattBatteryHealthStatus*)CsrPmemAlloc(sizeof(GattBatteryHealthStatus));
                    uint8* temp = (uint8*)value, sizeValue = 1;
                    SynMemCpyS(temp, sizeof(GattBatteryHealthStatus), &batteryHealthStatus.batteryHealthStatusFlags, sizeof(uint8));
                    temp += 1;
                    if (batteryHealthStatus.batteryHealthStatusFlags & BATTERY_HEALTH_SUMMARY_PRESENT) 
                    {
                        sizeValue += 1;
                        SynMemCpyS(temp, sizeof(GattBatteryHealthStatus), &batteryHealthStatus.batteryHealthSummary, sizeof(uint8));
                        temp += 1;
                    }
                    if (batteryHealthStatus.batteryHealthStatusFlags & CYCLE_COUNT_PRESENT) 
                    {
                        sizeValue += 2;
                        SynMemCpyS(temp, sizeof(GattBatteryHealthStatus), &batteryHealthStatus.cycleCount, sizeof(uint16));
                        temp += 2;
                    }
                    if (batteryHealthStatus.batteryHealthStatusFlags & CURRENT_TEMPERATURE_PRESENT) 
                    {
                        sizeValue += 1;
                        SynMemCpyS(temp, sizeof(GattBatteryHealthStatus), &batteryHealthStatus.currentTemperature, sizeof(int8));
                        temp += 1;
                    }
                    if (batteryHealthStatus.batteryHealthStatusFlags & DEEP_DISCHARGE_COUNT_PRESENT) 
                    {
                        sizeValue += 2;
                        SynMemCpyS(temp, sizeof(GattBatteryHealthStatus), &batteryHealthStatus.deepDischargeCount, sizeof(uint16));
                        temp += 2;
                    }
                    CsrBtGattNotificationEventReqSend(batteryServer->gattId, cids[index], HANDLE_BATTERY_HEALTH_STATUS, sizeValue, (uint8*)value);
                }
            }
        }
        else
        {
            result = FALSE;
        }
    }
    return result;
}

#endif /* EXCLUDE_GATT_BATTERY_SERVICE_V1P1 */